/**
 * @author xiaowei
 * @date 2017年4月25日
 */
Ext.define('App.view.common.CRUDGrid', {
    extend: 'Ext.grid.Panel',
    mixins: ['App.view.common.CommonFun'],
    xtype: 'crudgrid',
    _autoLoad: true,//自动请求数据
    openValidation: false,
    isCopyAdd: true,//当点击添加按钮时，是否启用复制新增功能。
    chineseName: '',//列表的中文名，编辑列表需要设置，提示时会作为标题提示
    allowBlank: true,//用于做数据验证（是否允许列表中没有数据）。true是允许，false不允许。
    pageSize: 20,//默认分页20条每页

    /*paramName: {//编辑列表获取参数的参数名配置。提交时将会按照配置的参数名提交
        add: 'addJson', //列表新增的数据
        update: 'updateJson',//列表编辑的数据
        del: 'delJson'//列表删除的数据
    },*/
    /*_mainConfs: [
     {name: 'name',type: 'string',text: '姓名'},
     {name: 'age',text: '年龄'},
     {name: 'email',type: 'string',text: '邮箱'},
     {name: 'date',type: 'date',text: '日期'}
     ],
     _validator: {name:{allowBlank:false},age:{minValue:0}},//数据验证器
     doNotValidEmpty: {name:true,age:true},//设置不需要验证的是否为空字段，该字段非空验证器将失效。
     */

    _confs: {//必要配置
        /*fields: [
         "name",
         'date',
         'age'
         ],
         url: '',//请求数据的url
         columns: ['name','date',{name:'age',width: 200}]*/
    },
    _record: '',//接收来自外部的传入的数据对象 {id:'1',name:''....}
    mainKeyName: '',//当列表作为主从表中的从表时，需要指定从表中主表的外键字段名称。指定之后，将默认将当前对象的_record属性中的id作为默认请求参数添加到defaultParams属性中,_autoLoad将强制置为true
    defaultParams: '',//defaultParams:{name: 12} 默认请求数据的参数，参数为对象
    columnsDefault: '',//columnsDefault:{align:'left',...} columns的默认属性值
    _isView: false,//是否是查看功能
    selType: "checkboxmodel",
    columnLines: true,
    rownumberer: true,//是否启用行号
    isRefreshRownum: true, //当编辑列表插入或删除数据时，是否刷新行号，默认刷新
    isPageGrid: true,//是否采用分页列表
    isShowSearchBar: false,//是否默认显示当前组件查询框
    defaultDatas: '',//默认数据defaultDatas:[{name: 'zhangsan'},{name: 'lisi'}] 默认数据
    editColIndex: 2,//编辑列表时，新增数据默认光标激活索引号为2的单元格
    viewConfig: {
        enableTextSelection: true
    },
    defaultSelectDatas: [],//默认选中的数据集，处于该数组中的数据，在每次load数据后，将自动处于选中状态
    autoScroll: true,
    rownumbererWidth: 40,
    rownumbererText: '',
    /*
     *配置参数
     */
    config: {
        isExport: false,
        exportFun: ''
    },
    //是否开启为每行添加操作按钮
    openRowButtons: false,
    //添加位置，start 每列的开头，end为每列的末尾
    rowButtonAlign: 'end',
    //需要添加的操作按钮
    rowButtons: [
        {
            bind: {hidden: '{update}'},
            xtype: 'button',
            margin: '0 5 0 0',
            iconCls: 'x-fa fa-pencil',
            cusType: 'edit',
            name:'u',
            handler: function () {
                var grid = this.up('grid');
                grid.getSelectionModel().select(this.ownerCt.$widgetRecord);
                if(grid.ownerGrid){
                    grid = grid.ownerGrid;
                }
                var btn = grid._toolbar.down('button[name=u]');
                setTimeout(function () {
                    grid._toolbar._update(btn);
                }, 10)
            }
        },
        {
            bind: {hidden: '{del}'},
            xtype: 'button',
            margin: '0 5 0 0',
            iconCls: 'x-fa fa-remove',
            cusType: 'del',
            name:'d',
            handler: function () {
                var grid = this.up('grid');
                grid.getSelectionModel().select(this.ownerCt.$widgetRecord);
                if(grid.ownerGrid){
                    grid = grid.ownerGrid;
                }
                var btn = grid._toolbar.down('button[name=d]');
                setTimeout(function () {
                    grid._toolbar._delete(btn);
                }, 20)
            }
        }
    ],
    initComponent: function () {
        if (!this.isLocked) {//修正由于锁列造成的二次初始化无法显示被锁列的缺陷
            this.initPhone();
            this._addValidator();
            this._setTools();
            this._initDefaultParams();
            this._setStore();
            this.columns = this._getColumns();
            this.addRowButtons();
            this._setPagingToolBar();
            this.showSearchBar();
        }else {
            this.style = {//锁定列表样式，增加阴影效果
                '-webkit-box-shadow':'0 0 10px #666',
                'border-width':'0px',
                'z-index':3
            }
        }

        if (this._isView || this.readOnly) {
            this.selModel = 'rowmodel';
        }

        this.callParent();
    },
    initPhone: function () {
        if (!Ext.platformTags.desktop) {
            if (this._confs && this._confs.columns) {
                var components = this._confs.columns;
                for (var i = 0; i < components.length; i++) {
                    //components[i].minWidth = 120;
                    if (components[i].flex) {
                        delete components[i].flex;
                    }
                }
            }
        }
    },
    /**
     * 对_toolbar操作栏中的按钮进行可用与不可用的逻辑控制
     * 需要继承该类的子类去实现selectControlButtons方法
     */
    actionControlLogic:function () {
        var me = this;
        if(this._toolbar){//如果存在操作工具栏，那么添加按钮操控逻辑
            this.openSelectControlButtons = true;
            this.on({
                beforeitemclick:function (th) {
                    if(me.selectControlButtons){
                        me._toolbar.enableOrDisableBtns(me.selectControlButtons(me.getSelectionModel().getSelection()));
                    }
                }
            });
        }
    },
    /**
     * 该方法需要在子类中实现方法体
     * 用途：选择数据时，控制操作栏按钮是否可用的逻辑
     * 传入一个records数组
     * 需要返回一个对象,标记操作按钮的可用与不可用状态
     * return {}
     * 示例： {c:true,d:true,u:false}  标识name为c和d的按钮可以使用，name为u的不能使用
     */
    selectControlButtons:function (records) {},

    addRowButtons: function () {
        if (!this.columns || !this.openRowButtons) {
            return;
        }
        var width = this.rowButtons.length * 45;
        if (this.rowButtonAlign === 'start') {
            this.columns.slice(0, 0, {
                width: width,
                text: '操作',
                xtype: 'widgetcolumn',
                align: 'center',
                widget: {
                    xtype: 'container',
                    layout: 'hbox',
                    items: Ext.clone(this.rowButtons)
                }
            });
        } else {
            this.columns.push({
                width: width,
                text: '操作',
                xtype: 'widgetcolumn',
                align: 'center',
                widget: {
                    xtype: 'container',
                    layout: 'hbox',
                    items: Ext.clone(this.rowButtons)
                }
            });
        }
        this.on({
            beforerender:function () {
                var me = this;
                var i,rows,k,widget,m,btnNames,btn;
                function getFirstProp(widgets){
                    for(i in widgets){
                        return widgets[i];
                    }
                }
                this.getStore().on({
                    load:function () {
                        if(!me.openSelectControlButtons){
                            return;
                        }
                        rows = me.liveRowContexts;
                        for(k in rows){
                            widget = getFirstProp(rows[k].widgets);
                            if(!widget){
                                continue;
                            }
                            btnNames = me.selectControlButtons([rows[k].record]);
                            if(!btnNames){
                                continue;
                            }
                            for(m in widget.items.keys){
                                btn = Ext.getCmp(widget.items.keys[m]);
                                if(btnNames[btn.name] === true){
                                    btn.enable();
                                }else if(btnNames[btn.name] === false){
                                    btn.disable();
                                }
                            }
                        }
                    }
                });
            }
        });
    },
    /**
     * 初始化默认请求参数
     * @private
     */
    _initDefaultParams: function () {
        if (this.mainKeyName) {
            if (!this._record) {
                return;
            }
            this._autoLoad = true;
            if (!this.defaultParams) {
                this.defaultParams = {};
            }
            if (!this.defaultParams[this.mainKeyName]) {
                this.defaultParams[this.mainKeyName] = this._record.id;
            }
        }

    },
    _setPagingToolBar: function () {
        if (this.isPageGrid) {
            var bbar = [];
            if (this.config.isExport) {
                bbar.push({
                    xtype: 'button',
                    text: '导出',
                    icon: './images/excel.png',
                    handler: this.config.exportFun
                });
                bbar.push('-');
            }

            bbar.push({
                xtype: 'pagingtoolbar',
                displayInfo: true,
                store: this.store,
                displayMsg: '当前显示 {0} - {1} 条,总数 {2}条',
                emptyMsg: "没有数据"
            });
            this.bbar = bbar;
            // this.bbar = {
            // 	xtype: 'pagingtoolbar',
            // 	displayInfo: true,
            // 	store: this.store,
            // 	displayMsg: '当前显示 {0} - {1} 条,总数 {2}条',
            // 	emptyMsg: "没有数据"
            // };
        }
    },

    _getFields: function () {
        if (!this._confs) {
            return;
        }
        var mcs = this._mainConfs,
            fs = this._confs.fields,
            fsRemove = this._confs.fieldsRemove,
            fsOverride = this._confs.fieldsOverride,
            temp, i, j, confObj, flag, type, field,
            fields = [];

        if (!fs && mcs) {//如果没有配置fields，那么自动根据_mainConfs生成fields
            for (i = 0; i < mcs.length; i++) {
                flag = true;
                type = mcs[i].type;
                if (!type) {
                    type = 'string';
                }

                if (fsRemove) {//判断是否配置需要移除的字段
                    for (j = 0; j < fsRemove.length; j++) {
                        if (mcs[i].name == fsRemove[j]) {
                            flag = false;
                        }
                    }
                }
                if (fsOverride && flag) {
                    for (j = 0; j < fsOverride.length; j++) {
                        confObj = fsOverride[j];
                        if (mcs[i].name == confObj.name) {
                            temp = this._getFieldByName(confObj.name);//该方法来自common.CommonFun对象
                            this._autoProperty(confObj, temp, ['name', 'type']);//自动生成
                            fields.push(confObj);
                            flag = false;
                        }
                    }
                }
                if (flag) {
                    field = {
                        name: mcs[i].name,
                        type: type
                    };

                    fields.push(field);

                }
            }
            return fields;
        } else if (fs) {//如果配置了fields，那么优先采用配置的fields

            for (i = 0; i < fs.length; i++) {
                confObj = fs[i];
                if (Ext.isString(confObj)) {//如果是字符串
                    temp = this._getFieldByName(confObj);//该方法来自common.CommonFun类
                    if (temp) {
                        type = temp.type;
                        if (!type) {
                            type = 'string';
                        }

                        field = {
                            name: temp.name,
                            type: type
                        };
                        fields.push(field);
                    } else {
                        fields.push(confObj);
                    }

                } else if (Ext.isObject(confObj)) {//如果是对象
                    temp = this._getFieldByName(confObj.name);//该方法来自common.CommonFun对象
                    this._autoProperty(confObj, temp, ['name', 'type']);//自动生成
                    fields.push(confObj);
                }
            }

        }
        return fields;
    },

    //将temp对象中的args字段复制到target对象中
    _autoProperty: function (target, temp, args) {

        if (!target.offAuto) {//是否自动生成开关，默认开启
            if (Ext.isString(args)) {
                if (!target.hasOwnProperty(args) && temp[args]) {
                    target[args] = temp[args];
                }
            }
            if (Ext.isArray(args)) {
                for (var i; i < args.length; i++) {
                    if (!target.hasOwnProperty(args[i]) && temp[args[i]]) {
                        target[args[i]] = temp[args[i]];
                    }
                }
            }
        }
    },

    _getColumns: function () {
        if (!this._confs) {
            return;
        }
        var mcs = this._mainConfs,
            cs = Ext.clone(this._confs.columns),
            csRemove = this._confs.columnsRemove ? Ext.Array.clone(this._confs.columnsRemove) : [],
            csOverride = this._confs.columnsOverride,
            temp, i, j, confObj, dataIndexName,
            flag, align,
            columns = [];

        if (this.rownumberer) {
            columns = [{
                text: this.rownumbererText,
                xtype: 'rownumberer',
                width: this.rownumbererWidth
            }];
        }
        var getFirstName = function (obj) {
            if (Ext.isString(obj)) {
                return obj;
            }
            if (obj.columns) {
                return getFirstName(obj.columns[0]);
            } else {
                return obj.dataIndex ? obj.dataIndex : obj.name;
            }
        };

        if (!cs && mcs) {//如果cs没有配置colums，那么自动根据_mainConfs生成columns
            for (i = 0; i < mcs.length; i++) {
                temp = mcs[i];
                flag = true;
                if (csRemove.length > 0) {//判断当前数据对象是否跳过生成列
                    flag = this._isRemain(csRemove, temp);
                }

                if (!flag) {
                    continue;
                }

                if (csOverride && flag) {//判断是否存在重写的列
                    csOverride = Ext.Array.clone(csOverride);
                    for (j = 0; j < csOverride.length; j++) {
                        confObj = csOverride[j];
                        if (getFirstName(confObj) == temp.name) {
                            this._getColumnByObject(confObj, csRemove);//列被重写后，把重写的名称加入csRemove中，避免重复生成列
                            columns.push(confObj);
                            Ext.Array.removeAt(csOverride, j);
                            flag = false;
                            break;
                        }
                    }
                }

                if (!flag) {
                    continue;
                }

                confObj = {flex: 1};
                this._autoColumnProperty(confObj, temp);
                columns.push(confObj);

            }
        } else if (cs) {//如果配置了columns，那么优先采用配置的columns

            for (i = 0; i < cs.length; i++) {
                confObj = cs[i];
                if (Ext.isString(confObj)) {//如果是字符串
                    columns.push(this._getColumnByString(confObj));
                } else if (Ext.isObject(confObj)) {//如果是对象
                    this._getColumnByObject(confObj);
                    columns.push(confObj);
                }
            }

        }
        return columns;
    },
    _isRemain: function (csRemove, obj) {
        var flag = true;
        for (var j = 0; j < csRemove.length; j++) {
            if (obj.name == csRemove[j]) {
                Ext.Array.removeAt(csRemove, j);
                flag = false;
                break;
            }
        }
        return flag;
    },
    _getColumnByString: function (confObj) {
        var column, temp;
        temp = this._getFieldByName(confObj);//该方法来自common.CommonFun类
        if (!temp) {
            alert('提示：dataMapping中没有找到字段名为[' + confObj + ']的映射对象！');
            return;
        }
        column = {};
        this._autoColumnProperty(column, temp);
        return column;
    },
    _getColumnByObject: function (confObj, csRemove) {
        var column, temp;

        if (confObj.columns) {//如果columns，证明配置是多列头。
            for (var i = 0; i < confObj.columns.length; i++) {
                if (Ext.isString(confObj.columns[i])) {//如果是字符串，转换成对象
                    confObj.columns[i] = this._getColumnByString(confObj.columns[i]);

                    if (Ext.isArray(csRemove)) {
                        csRemove.push(confObj.columns[i].dataIndex);
                    }

                } else if (Ext.isObject(confObj.columns[i])) {//如果是对象，继续递归
                    this._getColumnByObject(confObj.columns[i], csRemove);
                }
            }
        } else {//真正的column配置
            var dataIndexName = confObj.dataIndex ? confObj.dataIndex : false;
            if (!dataIndexName && confObj.name) {
                dataIndexName = confObj.name;
            }

            temp = this._getFieldByName(dataIndexName);//该方法来自common.CommonFun对象
            this._autoColumnProperty(confObj, temp);//自动添加默认属性

            if (Ext.isArray(csRemove)) {
                csRemove.push(dataIndexName);
            }

        }

    },

    _autoColumnProperty: function (target, temp) {
        if (this.columnsDefault) {
            Ext.applyIf(target, this.columnsDefault);
        }

        if (!target.offAuto && temp) {//是否自动生成开关，默认开启
            if (!target.hasOwnProperty('text') && temp.text) {
                target.text = temp.text;
            }
            if (!target.hasOwnProperty('dataIndex') && temp.name) {
                target.dataIndex = temp.name;
            }
            if (!target.hasOwnProperty('width')) {
                target.width = 100;
            }

            if (!target.hasOwnProperty('align') && temp.type) {
                target.align = 'left';
                if (temp.type == 'int' || temp.type == 'number' || temp.type == 'long' || temp.type == 'double') {
                    target.align = 'right';
                    if (!target.numberFormat && (temp.type == 'int' || temp.type == 'long')) {
                        target.numberFormat = '0,0';
                    }
                    else if (!target.numberFormat && (temp.type == 'number' || temp.type == 'double')) {
                        target.numberFormat = '0,0.00';
                    }
                } else if (temp.type == 'boolean') {
                    target.align = 'center';
                }
            }

            if (target.hyperlinkMode && !target.renderer) {//添加超链接效果
                target.renderer = function (val, metaData, record) {
                    if (!Ext.isEmpty(val)) {
                        return '<span style="color: blue;text-decoration:underline;cursor:pointer;">' + Ext.Component.htmlEscape(val) + '</span>';
                    }
                }
            }

            //添加详细页面配置
            if (target.hyperlinkWindow) {
                if (!target.listeners) {
                    target.listeners = {
                        click: function (grid, a, b, c, d, record) {
                            //修复拖动与点击事件冲突
                            if (d.parentEvent && (Math.abs(grid.grid.pointTop - d.parentEvent.touch.point.top) > 2 || Math.abs(grid.grid.pointLeft - d.parentEvent.touch.point.left) > 2)) {
                                return false
                            }
                            grid.ownerGrid.openHyperlinkWindow(record, target.hyperlinkWindow);
                        }
                    }
                } else if (!target.listeners.click) {
                    target.listeners.click = function (grid, a, b, c, d, record) {
                        //修复拖动与点击事件冲突
                        if (d.parentEvent && (Math.abs(grid.grid.pointTop - d.parentEvent.touch.point.top) > 2 || Math.abs(grid.grid.pointLeft - d.parentEvent.touch.point.left) > 2)) {
                            return false
                        }
                        grid.ownerGrid.openHyperlinkWindow(record, target.hyperlinkWindow);
                    }
                }
            }

            if (target.valueToName) {//是否将值转换为业务名称显示
                target.obj = Ext.create({
                    xtype: target.valueToName ? target.valueToName : target.dataIndex,
                    isInitChild: false
                });
                if (!target.renderer) {
                    target.renderer = function (val, metaData, record) {
                        return target.obj.valueToName(val, metaData, record);
                    }
                }
            }
        }

    },

    openHyperlinkWindow: function (record, hyperlinkWindow) {
        Ext.create({
            xtype: hyperlinkWindow,
            _record: record.data
        }).show();
    },
    _searchPage: function (params) {
        this._search(params, true);
    },
    _search: function (params, useCurrentPage) {
        var store
            , proxy
        ;

        store = this.getStore();

        if (params) {
            if (this.defaultParams) {
                params = Ext.apply(Ext.clone(this.defaultParams), params);
            }
            proxy = store.getProxy();
            proxy.extraParams = params;

        }

        if (this.isPageGrid) {
            if (useCurrentPage) {
                store.loadPage(store.currentPage);
            } else {
                store.loadPage(1);
            }

        } else {
            store.load();
        }
    },

    /**
     * 设置store类名，如果参数为空，默认采用Ext.data.Store
     * @param className String 类名
     * @param configs Object 配置对象
     * @private
     */
    _setStore: function (className, configs) {
        var me = this,
            params = '',
            url = this._confs.url;
        if (!className) {
            className = 'Ext.data.Store';
        }

        if (!url) {
            url = this.url;
        }

        if (this.defaultParams) {
            params = Ext.clone(this.defaultParams);
        }
        var baseConfig = {
            //fields:this._getFields(),
            model: this._getModel(),
            pageSize: this.pageSize,
            proxy: {
                type: 'ajax',
                url: url,
                extraParams: params,
                reader: {
                    type: 'json',
                    rootProperty: 'list',
                    totalProperty: 'total'
                }
            },
            autoLoad: me._autoLoad
        };
        if (configs) {
            Ext.applyIf(configs, baseConfig);
        } else {
            configs = baseConfig;
        }
        this.store = Ext.create(className, configs);

        if (this.defaultDatas) {
            this.store.loadData(Ext.clone(this.defaultDatas));
        }
    },

    /**
     * 隐藏工具按钮
     * param {[btnName]:true|false} true隐藏
     */
    hideTools:function (names) {
        if(!names){
            return;
        }
        for(var i in names){
            if(this.down('button[name='+i+']')){
                if(names[i]){
                    this.down('button[name='+i+']').hide();
                }else{
                    this.down('button[name='+i+']').show();
                }
            }
        }
    },
    _setTools: function () {
        var me = this, i, temp;
        var base = {
            getRefresh: function () {
                return {
                    itemId: 'refresh',
                    xtype: 'button',
                    margin: '0 5',
                    iconCls: "x-fa fa-refresh",
                    name: 'refresh',
                    tooltip: '刷新',
                    handler: function (owner) {
                        owner.up('grid')._refresh();
                    }
                }
            },
            getPlus: function () {
                return {
                    xtype: 'button',
                    iconCls: 'x-fa fa-plus',
                    margin: '0 5',
                    name: 'plus',
                    bind:{disabled:'{plus}'},
                    tooltip: '添加数据（选中多行，可以进行复制添加）',
                    handler: function (owner) {
                        owner.up('grid')._addRecords();
                    }
                }
            },
            getMinus: function () {
                return {
                    xtype: 'button',
                    iconCls: 'x-fa fa-minus',
                    margin: '0 5',
                    cusType: 'del',
                    name: 'minus',
                    bind:{disabled:'{minus}'},
                    tooltip: '删除数据',
                    handler: function (owner, recIndex, cellIndex, item, e, record) {
                        owner.up('grid')._removeRecords();
                    }
                }
            },
            getMultiEdit: function () {
                return {
                    xtype: 'button',
                    tooltip: '批量修改',
                    text: '批量修改',
                    iconCls: 'x-fa fa-edit',
                    margin: '0 5',
                    name: 'multiEdit',
                    bind:{disabled:'{multiEdit}'},
                    actionObject: '',//必须传入操作表单xtype
                    handler: function (btn) {
                        btn.up('grid')._multiEdit(btn);
                    }
                }
            }
        };
        if (this.tools) {
            for (i = 0; i < this.tools.length; i++) {
                temp = this.tools[i];
                if (Ext.isObject(temp)) {
                    if (temp.name == 'refresh') {
                        Ext.applyIf(temp, base.getRefresh());
                    } else if (temp.name == 'plus') {
                        Ext.applyIf(temp, base.getPlus());
                    } else if (temp.name == 'minus') {
                        Ext.applyIf(temp, base.getMinus());
                    } else if (temp.name == 'multiEdit') {
                        Ext.applyIf(temp, base.getMultiEdit());
                    }
                }
                if (Ext.isString(temp)) {
                    if (temp == 'refresh') {
                        this.tools[i] = base.getRefresh();
                    }
                    else if (temp == 'plus') {
                        this.tools[i] = base.getPlus();
                    }
                    else if (temp == 'minus') {
                        this.tools[i] = base.getMinus();
                    }
                    else if (temp == 'multiEdit') {
                        this.tools[i] = base.getMultiEdit();
                    }
                }
            }
        }

    },
    defaultMultiEditForm:function () {
        var cols = this.columns;
        var items=[],temp,editor,i;
        //复制时，需要排除的数据
        // var excludeField = {childEls:true,column:true,triggers:true,value:true};
        for(var key in cols){
            if(cols[key].isMultiEdit && cols[key].dataIndex){
                if(!cols[key].hidden && cols[key].getEditor()){
                    editor = cols[key].initialConfig.editor;
                    temp = {
                        value:'',
                        fieldLabel:cols[key].text,
                        name:cols[key].dataIndex,
                        xtype:editor.xtype
                    };
                    items.push(Ext.applyIf(temp,editor));
                }
            }
        }
        return {
            xtype:'commonform',
            layout: 'anchor',
            bodyPadding: 10,
            defaults: {
                anchor: '100%'
            },
            defaultType: 'textfield',
            items:items
        }
    },
    //多选编辑之前的验证逻辑
    _multiEditValid:function (selectNodes) {
        if (Ext.isEmpty(selectNodes)) {
            return false;
        }
        return true;
    },
    _multiEdit: function (btn) {
        var me = this;
        var currentNodes;
        currentNodes = me.getSelectRecords(true);
        if(!me._multiEditValid(currentNodes)){
            return;
        }
        var form,width = 800;
        if (!btn.actionObject) {
            form = this.defaultMultiEditForm();
            width = 600;
        }else {
            form = {xtype:btn.actionObject};
        }
        Ext.create('App.view.common.Window', {
            title: '批量修改 <span style="color: red">不填写内容不会被修改！</span>',
            width:width,
            items: [
                form
            ],
            setMultiEditValue: function (data) {
                var key;
                for (var i = 0; i < currentNodes.length; i++) {
                    for (key in data) {
                        if (!Ext.isEmpty(data[key])) {
                            currentNodes[i].set(key, data[key]);
                        }
                    }
                }
            },
            _onSubmit: function (btn) {
                var win = btn.up('commonwindow');
                var values = win.down('form').getValues();
                win.setMultiEditValue(values);
                win.close();
            },
            buttons: [
                {
                    xtype: 'button', text: '重置',
                    handler: function () {
                        this.up('commonwindow').down('form').getForm().reset();
                    }
                },
                {name: 'submit',text:'确定'}
                , 'close'
            ]
        }).show();
    },

    _refresh: function () {
        var store
            , proxy
            , params = {}
        ;

        store = this.getStore();
        proxy = store.getProxy();
        if (this.defaultParams) {
            params = this.defaultParams;
        }

        proxy.extraParams = params;
        if (this.isPageGrid) {
            store.loadPage(store.currentPage);
        } else {
            store.load();
        }
    },

    _addRecords: function () {
        var selections,
            me = this,
            recs = [],
            i,
            defaultData, count = this.store.getCount();
        selections = this.getSelectionModel().getSelection();
        if (selections.length > 0 && this.isCopyAdd) {
            for (i = 0; i < selections.length; i++) {
                recs.push(Ext.applyIf({id: '', _add: true}, selections[i].data));
            }
        } else {
            defaultData = this.defaultDatas ? Ext.clone(this.defaultDatas) : [{}];
            for (i in defaultData) {
                defaultData[i].add = true;
            }
            recs = defaultData;
        }
        this.store.insert(this.store.getCount(), recs);
        if (!Ext.isEmpty(this.editColIndex)) {
            setTimeout(function () {
                me.findPlugin('cellediting').startEditByPosition({row: me.store.getCount(), column: me.editColIndex});
            }, 10)

        }
        if (this.isRefreshRownum) {
            this.getView().refresh();
        }
    },

    //移除列表数据前的验证逻辑
    _removeValid:function (selections) {
        if (!selections || selections.length < 1) {
            App.ux.Toast.show('提示', '请选中需要删除的行！ <span style="color:red;">*</span>支持多行','i');
            return false;
        }
        return true;
    },
    _removeRecords: function () {
        var selections;

        selections = this.getSelectionModel().getSelection();
        if (!this._removeValid(selections)) {
            return;
        }
        this.store.remove(selections);
        if (this.isRefreshRownum) {
            this.getView().refresh();
        }
    },

    _getSelectionDataIds: function () {
        var records = this.getSelection();
        var datas = [], record, i;
        for (i = 0; i < records.length; i++) {
            datas.push(records[i].get('id'))
        }
        return datas;
    },

    _getSelectionProcessInstanceIds: function () {
        var records = this.getSelection();
        var datas = [], record, i;
        for (i = 0; i < records.length; i++) {
            datas.push(records[i].get('processInstanceId'))
        }
        return datas;
    },

    //客户自定义验证逻辑，需要返回valid对象{valid: true, message: ''}
    _customValid: function () {
        var valid = {valid: true, message: ''};
        return valid;
    },
    /**
     * 逐条验证数据合法性
     * @param data
     * @param validator
     * @param record
     * @returns {{valid: boolean, message: string}}
     * @private
     */
    _validData: function (data, validator, record) {
        var valid = {
            valid: true,
            message: ''
        };

        for (var obj in validator) {
            if (validator[obj] && Ext.isEmpty(data[obj])) {//如果验证其中存在该字段，那么该字段将不允许为空值
                if (this.doNotValidEmpty && this.doNotValidEmpty[obj]) {//如果配置不需要验证的字段，跳过验证
                    continue;
                }
                valid.valid = false;
                valid.message += '【' + validator[obj].text.replace("<br>", "", "gi") + '】';
            }
        }
        if (!valid.valid) {
            valid.message += '不能为空</br>';
        }
        return valid;
    },
    //表格grid对自己列表数据进行验证，
    _gridValid: function (data) {
        if (!this.openValidation) {//如果验证器处于关闭状态，不做验证
            return {
                valid: true,
                message: 'openValidation属性为false，验证器处于关闭状态，跳过验证</br>'
            };
        }
        var store = this.getStore(),
            validator = this._createValidator(),
            valid = {valid: true, message: ''},
            me = this;
        if (!this.allowBlank && store.getCount() < 1) {
            valid.valid = false;
            valid.message = '列表不允许为空</br>';
            return valid;
        }

        if (!validator) {
            return valid;
        }

        if (data) {
            return this._validData(data, validator);
        }

        store.each(function (record, i) {
            var validResult, i = i + 1;
            validResult = me._validData(record.data, validator, record);
            if (!validResult.valid) {
                valid.valid = false;
                valid.message += '第' + i + '行:' + validResult.message;
            }

        });
        return valid;
    },
    isValid: function () {
        var form = this.down('form'),
            valid = true,
            message = this.chineseName + '<br>',
            customValid,
            gridValid;

        if (!this.openValidation) {//如果验证器处于关闭状态，不做验证
            return {
                valid: true,
                message: message + 'openValidation属性为false，验证器处于关闭状态，跳过验证<br>'
            };
        }
        if (form && !form.getForm().isValid()) {
            return {
                valid: false,
                message: message + '表单存在非法输入内容<br>'
            };
        }
        gridValid = this._gridValid();
        if (!gridValid.valid) {
            gridValid.message = message + gridValid.message;
            return gridValid;
        }
        //如果框架默认验证通过之后
        //执行用户自定义验证机制
        customValid = this._customValid();
        if (!customValid.valid) {
            valid = false;
            message += customValid.message;
        }

        return {
            valid: valid,
            message: message
        };
    },
    getDatas: function () {
        var store = this.getStore();
        var values = [], temp;
        store.each(function (record, i) {
            temp = Ext.apply({}, record.data);
            if (temp.id && Ext.isString(temp.id) && temp.id.substring(0, 4) == "extM") {
                temp.id = '';
            }
            values.push(temp);

        });
        return values;
    },
    getEncodeValues: function () {
        return this.getValues(true);
    },

    getEncodeChangeValues: function () {
        return this.getChangeValues(true);
    },

    getChangeValues: function (isEncode) {
        var store = this.getStore();
        var values = [], value = {},
            formValues, temp, modifyDatas, newDatas, removeDatas,
            modifys = [], removes = [], key,
            i;

        modifyDatas = store.getUpdatedRecords();
        newDatas = store.getNewRecords();
        removeDatas = store.getRemovedRecords();

        if (modifyDatas) {
            for (i = 0; i < modifyDatas.length; i++) {
                temp = modifyDatas[i].getChanges();
                temp.id = modifyDatas[i].data.id;
                for (key in temp) {
                    if (Ext.isEmpty(temp[key])) {
                        temp[key] = '';
                    }
                }
                modifys.push(Ext.copy({}, temp, this._BaseDataFields));
            }
        }

        if (newDatas) {
            for (i = 0; i < newDatas.length; i++) {
                temp = newDatas[i].data;
                if (temp.id && Ext.isString(temp.id) && temp.id.substring(0, 4) == "extM") {
                    temp.id = '';
                }
                values.push(Ext.copy({}, temp, this._BaseDataFields));
            }
        }

        if (removeDatas) {
            for (i = 0; i < removeDatas.length; i++) {
                if (removeDatas[i].data.id) {
                    removes.push(removeDatas[i].data.id);
                }
            }
        }

        formValues = this.getFormChangeValues();

        if (Ext.isEmpty(values) && Ext.isEmpty(formValues) && Ext.isEmpty(modifys) && Ext.isEmpty(removes)) {
            return;
        }

        if (isEncode) {
            if (!Ext.isEmpty(values)) {
                values = Ext.encode(values);
            }
            if (!Ext.isEmpty(modifys)) {
                modifys = Ext.encode(modifys);
            }
        }

        if (Ext.isObject(this.paramName)) {
            if (this.paramName.add && !Ext.isEmpty(values)) {
                value[this.paramName.add] = values;
            }
            if (this.paramName.update && !Ext.isEmpty(modifys)) {
                value[this.paramName.update] = modifys;
            }
            if (this.paramName.del && !Ext.isEmpty(removes)) {
                value[this.paramName.del] = removes.toString();
            }

        } else if (this.name) {
            if (!Ext.isEmpty(values)) {
                value[this.name] = values;
            }
            if (!Ext.isEmpty(modifys)) {
                value[this.name + 'modify'] = modifys;
            }
            if (!Ext.isEmpty(removes)) {
                value[this.name + 'removes'] = removes.toString();
            }
        }

        if (formValues) {
            value = Ext.apply(value, formValues);
        }

        return value;
    },
    setValue: function (datas) {
        this.getStore().insert(this.getStore().getCount(), datas);
    },
    setValues: function (datas) {

    },
    /**
     * 获取列表需要提交的数据，与Data映射对象字段一致
     * @returns {Array}
     */
    getVals: function () {
        var store = this.getStore();
        var values = [], me = this, temp;

        store.each(function (record, i) {
            temp = Ext.copy({}, record.data, me._BaseDataFields);

            if (temp.id && Ext.isString(temp.id) && temp.id.substring(0, 4) == "extM") {
                temp.id = '';
            }
            values.push(temp);

        });
        return values;
    },
    /**
     * isEncode为ture将encode数据
     * @param isEncode
     * @returns {{}}
     */
    getValues: function (isEncode) {
        var values = this.getVals(), value = {}, me = this,
            formValues;

        formValues = this.getFormValues();

        if (Ext.isEmpty(values) && Ext.isEmpty(formValues)) {
            return;
        }

        if (isEncode) {
            if (!Ext.isEmpty(values)) {
                values = Ext.encode(values);
            }
        }

        if (Ext.isObject(this.paramName)) {
            if (this.paramName.add && !Ext.isEmpty(values)) {
                value[this.paramName.add] = values;
            }
        } else {
            if (this.name) {
                value[this.name] = values;
            } else {
                value[this.getId()] = values;
            }
        }

        if (formValues) {
            value = Ext.apply(value, formValues);
        }

        return value;
    },
    getFormValues: function () {
        var form = this.down('form');
        var values;
        if (form) {
            values = form.getForm().getValues();
        }
        return values;
    },

    getFormChangeValues: function (requires) {
        var form = this.down('form');
        var values;
        if (form) {
            values = form.getChangeValues(requires);
        }
        return values;
    },

    _getModel: function () {
        var fields = this._getFields();
        var model = Ext.create('Ext.data.Model', {
            fields: fields,
            validators: this._createValidator()
        });
        return model;
    },

    _createValidator: function () {
        var mc = this._mainConfs, temp, validator = {};
        if (!mc) {
            return '';
        }
        if (this.validator) {
            return this.validator;
        }

        for (var i = 0; i < mc.length; i++) {
            temp = mc[i];
            if (temp.validator) {
                if (temp.validator.allowBlank === false) {
                    validator[temp.name] = {
                        text: temp.text
                    };
                }
            }
        }
        this.validator = validator;
        return validator;
    },
    showSearchBar: function () {
        var me = this;
        if (!this.isShowSearchBar) {
            return;
        }
        var searchBar = {
            xtype: 'textfield',
            //maxWidth: 300,
            name: 'searchField',
            dock: 'top',
            emptyText: '请输名称',

            triggers: {
                clear: {
                    cls: 'x-form-clear-trigger',
                    handler: function (cmp) {
                        me.down('textfield[name=searchField]').setValue();
                        me._refresh();
                    },
                    hidden: true
                },
                search: {
                    cls: 'x-form-search-trigger',
                    weight: 1,
                    handler: function (cmp) {
                        var param = {};
                        param[me.filterName] = me.down('textfield[name=searchField]').getValue();
                        me._search(param);
                    }
                }
            },

            listeners: {
                change: function (field, newValue) {
                    var param = {};
                    if (newValue) {
                        field.triggers.clear.show();
                    } else {
                        field.triggers.clear.hide();
                    }
                    param[me.filterName] = newValue;
                    me._search(param);
                },
                buffer: 300,
                boxready: function () {
                    this.setWidth(me.getWidth());
                }
            }
        };
        if (this.dockedItems) {
            this.dockedItems.push(searchBar);
        } else {
            this.dockedItems = [searchBar];
        }
    }
});